<template>
  <div>
    <el-row :gutter="10" style="margin-top: 20px; margin-left: 20px">
      <el-col :span="4">
        <el-input
          v-model="deptName"
          placeholder="请输入部门名称"
          clearable
          size="small"
          prefix-icon="el-icon-search"
          style="margin-bottom: 20px"
        />
        <!-- 部门树形组件 -->
        <div class="tree-container">
          <el-tree
            ref="tree"
            node-key="deptId"
            :data="depts"
            :props="defaultProps"
            :expand-on-click-node="false"
            default-expand-all
            :filter-node-method="filterNode"
            @node-click="handleNodeClick"
          >
            <!-- 树组件自定义节点内容 -->
            <template #default="{ data }">
              <el-row type="flex" justify="space-between" align="middle">
                <el-col :span="24">{{ data.deptName }}</el-col>
              </el-row>
            </template>
          </el-tree>
        </div>
      </el-col>
      <!-- 用户搜索部分 -->
      <el-col :span="20">
        <el-form ref="form" label-width="80px" :model="userDto" :inline="true">
          <el-form-item label="用户名称">
            <el-input
              v-model="userDto.username"
              size="small"
              placeholder="请输入用户名称"
              prefix-icon="el-icon-search"
            />
          </el-form-item>
          <el-form-item label="手机号">
            <el-input
              v-model="userDto.phoneNumber"
              size="small"
              placeholder="请输入手机号"
              prefix-icon="el-icon-mobile-phone"
            />
          </el-form-item>
          <el-form-item label="邮箱">
            <el-input v-model="userDto.email" size="small" placeholder="请输入手机号" prefix-icon="el-icon-message" />
          </el-form-item>
          <el-form-item label="状态">
            <el-select v-model="userDto.status">
              <el-option label="正常" :value="false" />
              <el-option label="停用" :value="true" />
            </el-select>
          </el-form-item>
          <el-form-item>
            <el-button type="primary" icon="el-icon-search" size="mini" @click="onSearch">搜索</el-button>
            <el-button icon="el-icon-refresh" size="mini" @click="refresh">重置</el-button>
          </el-form-item>
        </el-form>
        <el-row>
          <el-col :span="24">
            <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="addUser">新增用户</el-button>
            <el-button type="info" plain icon="el-icon-upload2" size="mini">导入</el-button>
            <el-button type="warning" plain icon="el-icon-download" size="mini">导出</el-button>
          </el-col>
        </el-row>
        <!-- 右侧表格 -->
        <div class="table-container">
          <el-table
            v-loading="loading"
            border
            :data="tableData"
            style="width: 100%"
            :row-class-name="tableRowClassName"
          >
            <el-table-column type="selection" width="30" prop="userId" />
            <el-table-column prop="username" label="用户账号" width="120" align="center" />
            <el-table-column prop="nickName" label="用户昵称" width="150" align="center" />
            <el-table-column prop="email" label="邮箱" width="180" align="center" />
            <el-table-column prop="phoneNumber" label="手机号" width="150" align="center" />
            <el-table-column prop="sex" label="性别" width="100" align="center">
              <template #default="scope">
                {{ scope.row.sex === 1 ? '男' : '女' }}
              </template>
            </el-table-column>
            <el-table-column prop="avatar" label="头像" width="150" align="center">
              <template #default="scope">
                <img :src="scope.row.avatar" alt="头像" style="width: 50px; height: 50px; border-radius: 50%" />
              </template>
            </el-table-column>
            <el-table-column prop="status" label="状态" width="80" align="center">
              <template #default="scope">
                <el-switch
                  v-model="scope.row.status"
                  active-color="#ff4949"
                  inactive-color="#13ce66"
                  @change="changeSwitch(scope.row.userId, scope.row.status)"
                />
              </template>
            </el-table-column>
            <el-table-column label="操作" align="center">
              <template slot-scope="scope">
                <el-button size="mini" type="warning" @click="handleEdit(scope.row.userId)">编辑</el-button>
                <el-button size="mini" type="danger" @click="handleDelete(scope.row.userId)">删除</el-button>
                <el-button size="mini" type="success" @click="handleAssignDialog(scope.row)"> 分配角色 </el-button>
              </template>
            </el-table-column>
          </el-table>

          <!-- 表格下方放置一个分页组件，并使其水平居中 -->
          <el-row type="flex" justify="center" style="margin-top: 20px">
            <el-col :span="12">
              <!-- 根据需要调整 span 值 -->
              <!-- 表格下方放置一个分页组件 -->
              <el-pagination
                :current-page="page"
                :page-sizes="[5, 10, 20, 30]"
                :page-size="pageSize"
                layout="total, sizes, prev, pager, next, jumper"
                :total="total"
                prev-text="上一页"
                next-text="下一页"
                @size-change="handleSizeChange"
                @current-change="handleCurrentChange"
              />
            </el-col>
          </el-row>
        </div>
      </el-col>
    </el-row>
    <!-- 新增用户弹窗 -->
    <el-dialog title="新增" :visible.sync="dialogVisible" width="40%" :before-close="handleClose">
      <el-form ref="userForm" :model="userForm" size="mini" label-width="80px" :rules="rules">
        <el-form-item label="账号" prop="username">
          <el-input v-model="userForm.username" clearable />
        </el-form-item>
        <el-form-item label="昵称" prop="nickName">
          <el-input v-model="userForm.nickName" clearable minlength />
        </el-form-item>
        <el-form-item label="邮箱" prop="email">
          <el-input v-model="userForm.email" clearable minlength />
        </el-form-item>
        <el-form-item label="手机号" prop="phoneNumber">
          <el-input v-model="userForm.phoneNumber" clearable minlength />
        </el-form-item>
        <el-form-item label="性别" prop="sex">
          <el-radio v-model="userForm.sex" :label="1">男</el-radio>
          <el-radio v-model="userForm.sex" :label="0">女</el-radio>
        </el-form-item>
        <el-form-item label="部门" prop="deptId">
          <!--  @change="handleChange" 当选择某一个级别的时候，触发的函数 -->
          <el-cascader
            v-model="userForm.deptId"
            :options="deptOptions"
            :props="cascaderProps"
            :show-all-levels="false"
          />
        </el-form-item>

        <!-- 新增：上传图片 -->
        <!--action是自动上传的地址，这个项目不需要 我们需要手动上传  -->
        <!-- :show-file-list="false" 不展示列表 -->
        <!-- :before-upload="beforeAvatarUpload" 检查上传前的函数 -->
        <!-- :http-request="uploadImage"覆盖默认的上传行为，可以自定义上传的实现 -->
        <el-form-item label="头像" prop="avatar">
          <el-upload
            class="avatar-uploader"
            action=""
            :show-file-list="false"
            :auto-upload="false"
            :on-change="handleAvatarChange"
            :before-upload="beforeAvatarUpload"
          >
            <img v-if="userForm.avatar" :src="userForm.avatar" class="avatar" />
            <i v-else class="el-icon-plus avatar-uploader-icon" />
          </el-upload>
        </el-form-item>
        <el-form-item label="备注" prop="remark">
          <el-input v-model="userForm.remark" type="textarea" :rows="4" placeholder="请输入内容" />
        </el-form-item>
        <el-form-item>
          <el-button size="mini" style="margin-right: 200px" @click="closeAddUserDialog">取 消</el-button>
          <el-button type="primary" size="mini" @click="submitForm">确 定</el-button>
        </el-form-item>
      </el-form>
    </el-dialog>

    <!-- 编辑用户弹窗 -->
    <el-dialog title="编辑" :visible.sync="editDialogVisible" width="40%" :before-close="handleClose">
      <el-form ref="userForm" :model="userForm" size="mini" label-width="80px" :rules="rules">
        <el-form-item label="账号" prop="username">
          <el-input v-model="userForm.username" clearable />
        </el-form-item>
        <el-form-item label="昵称" prop="nickName">
          <el-input v-model="userForm.nickName" clearable minlength />
        </el-form-item>
        <el-form-item label="邮箱" prop="email">
          <el-input v-model="userForm.email" clearable minlength />
        </el-form-item>
        <el-form-item label="手机号" prop="phoneNumber">
          <el-input v-model="userForm.phoneNumber" clearable minlength />
        </el-form-item>
        <el-form-item label="性别" prop="sex">
          <el-radio v-model="userForm.sex" :label="1">男</el-radio>
          <el-radio v-model="userForm.sex" :label="0">女</el-radio>
        </el-form-item>
        <el-form-item label="部门" prop="deptId">
          <!--  @change="handleChange" 当选择某一个级别的时候，触发的函数 -->
          <el-cascader
            v-model="userForm.deptId"
            :options="deptOptions"
            :props="cascaderProps"
            :show-all-levels="false"
          />
        </el-form-item>

        <!-- 新增：上传图片 -->
        <!--action是自动上传的地址，这个项目不需要 我们需要手动上传  -->
        <!-- :show-file-list="false" 不展示列表 -->
        <!-- :before-upload="beforeAvatarUpload" 检查上传前的函数 -->
        <!-- :http-request="uploadImage"覆盖默认的上传行为，可以自定义上传的实现 -->
        <el-form-item label="头像" prop="avatar">
          <el-upload
            class="avatar-uploader"
            action=""
            :show-file-list="false"
            :auto-upload="false"
            :on-change="handleAvatarChange"
            :before-upload="beforeAvatarUpload"
          >
            <img v-if="userForm.avatar" :src="userForm.avatar" class="avatar" />
            <i v-else class="el-icon-plus avatar-uploader-icon" />
          </el-upload>
        </el-form-item>
        <el-form-item label="备注" prop="remark">
          <el-input v-model="userForm.remark" type="textarea" :rows="4" placeholder="请输入内容" />
        </el-form-item>
        <el-form-item>
          <el-button size="mini" style="margin-right: 200px" @click="closeEditUserDialog">取 消</el-button>
          <el-button type="primary" size="mini" @click="updateSubmitForm">确 定</el-button>
        </el-form-item>
      </el-form>
    </el-dialog>
    <AssignDialog v-if="assignShowVisible || user" :assign-show-visible.sync="assignShowVisible" :user="user" />
  </div>
</template>
<script>
  import AssignDialog from './components/AssignDialog.vue'
  import { getDepartment } from '@/api/dept'
  import { listToTree, buildDeptTree } from '@/utils/index'
  import { pageList, insertUser, updateUserStatus, deleteByUserId, findByUserId, updateUser } from '@/api/user'
  export default {
    components: {
      AssignDialog
    },
    data() {
      return {
        loading: false,
        dialogVisible: false,
        editDialogVisible: false,
        assignShowVisible: false, // 控制分配权限的弹窗显示/隐藏
        user: null, // 分配角色时候的选择的用户id
        page: 1,
        pageSize: 5,
        total: 0, // 总记录数
        userDto: {
          username: '',
          nickName: '',
          status: 'false',
          email: '',
          phoneNumber: '',
          deptId: '' // 部门id
        }, // 搜索条件对象
        deptName: '',
        // el-tree组件的属性名称配置
        defaultProps: {
          children: 'children',
          label: 'deptName'
        },
        tableData: [], // 表格数据
        depts: [], // 部门树形结构
        userForm: {
          deptId: null,
          username: '',
          nickName: '',
          email: '',
          phoneNumber: '',
          sex: 1,
          avatarFile: null,
          avatar: '',
          remark: ''
        },
        deptOptions: [], // dialog组件中el-cascader级联选择器需要的树形结构数据
        cascaderProps: {
          expandTrigger: 'hover',
          value: 'deptId', // 绑定选中时候的字段
          label: 'deptName', // 选择框中需要显示的明文字段
          checkStrictly: true, // 允许选择任意级别
          emitPath: false // 只返回选中的值而不是路径数组
        },
        rules: {
          username: [
            { required: true, message: '账号不能为空', trigger: 'blur' },
            { min: 4, max: 16, message: '长度在 4 到 16 个字符', trigger: 'blur' },
            {
              validator: (rule, value, callback) => {
                const isLowerCase = /^[a-z]+$/.test(value)
                if (!isLowerCase) {
                  callback(new Error('必须是全英文小写'))
                } else {
                  callback()
                }
              },
              message: '必须是全英文小写',
              trigger: 'blur'
            }
          ],
          nickName: [
            { required: true, message: '昵称不能为空', trigger: 'blur' },
            { min: 2, max: 6, message: '长度在 2 到 6 个字符', trigger: 'blur' }
          ],
          email: [
            { required: true, message: '邮箱不能为空', trigger: 'blur' },
            {
              pattern: /^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$/,
              message: '请输入有效的邮箱地址',
              trigger: 'blur'
            }
          ],
          phoneNumber: [
            { required: true, message: '手机号不能为空', trigger: 'blur' },
            {
              pattern: /^1[3-9]\d{9}$/, // 匹配中国手机号的正则表达式
              message: '请输入有效的11位手机号码',
              trigger: 'blur'
            }
          ],
          deptId: [{ required: true, message: '请选择部门', trigger: 'change' }],
          avatar: [{ required: true, message: '请上传头像', trigger: 'change' }],
          remark: [{ min: 0, max: 100, message: '长度在 0 到 100 个字符', trigger: 'blur' }]
        }
      }
    },
    watch: {
      // 此方法会在部门输入框中的值发生变化的时候，触发
      deptName(val) {
        // 拿到树组件实例,触发这个组件的filter()方法，这个方法要求在树组件中必须定义 :filter-node-method="filterNode"
        // 然后会执行filterNode这个方法，进行过滤树节点
        this.$refs.tree.filter(val)
      }
    },
    created() {
      this.getDepartment()
      this.pageList()
    },
    methods: {
      /**
       *筛选节点
       */
      filterNode(value, data) {
        if (!value) return true // 如果过滤关键字为空，则显示所有节点
        return data.deptName.indexOf(value) !== -1 // 根据deptName字段判断是否包含过滤关键字
      },
      /**
       * 获取部门数组列表
       */
      async getDepartment() {
        const deptsList = await getDepartment()
        // 将数据转为前段需要的树形结构
        this.depts = listToTree(deptsList, '0')
        // 将数据转为Cascader 级联选择器需要的树形格式
        this.deptOptions = buildDeptTree(deptsList, '0')
      },
      /**
       * 获取用户分页列表方法
       */
      async pageList() {
        this.loading = true
        const { total, list } = await pageList(this.page, this.pageSize, this.userDto)
        this.tableData = list
        this.total = total
        this.loading = false
      },
      /**
       * 点击树节点触发这个函数，这个data是当前点击的这个数据对象
       * @param data
       */
      handleNodeClick(data) {
        // console.log(data.deptId)
        this.userDto.deptId = data.deptId
        this.pageList()
      },
      /**
       * 搜索
       */
      onSearch() {
        this.pageList()
      },
      /**
       * 重置
       */
      refresh() {
        this.userDto = { status: 'false' }
        this.deptName = ''
        this.pageList()
        this.getDepartment()
        // this.$refs.form.resetFields()
      },
      /**
       * 选择每页显示多少条时候触发
       * @param pageSize
       */
      handleSizeChange(pageSize) {
        // console.log(`每页 ${val} 条`)
        this.pageSize = pageSize
        this.pageList()
      },
      /**
       *点击页码数发生变化时候触发
       * @param page
       */
      handleCurrentChange(page) {
        // console.log(`当前页: ${val}`)
        this.page = page
        this.pageList()
      },
      /**
       * 新增用户
       */
      addUser() {
        // 开启弹窗
        this.dialogVisible = true
      },
      /**
       * 点击x号，关闭弹窗
       * @param done
       */
      handleClose(done) {
        // 重置表单内容
        this.resetForm()
        done()
      },
      /**
       * 点击取消按钮，关闭弹窗
       */
      closeAddUserDialog() {
        // 重置表单内容
        this.resetForm()
        this.dialogVisible = false
      },
      /**
       * 选择
       */
      // handleChange(value) {
      //   console.log('你选择的部门deptId是:', value)
      //   // 这里可以根据需要进行进一步处理
      //   // this.userForm.deptId = value
      // },
      /**
       * :before-upload="beforeAvatarUpload"
       * 文件上传之前执行的校验逻辑
       * @param file
       */
      beforeAvatarUpload(file) {
        console.log('beforeAvatarUpload方法执行,开始校验文件格式和大小')

        // 支持的图片格式
        const isSupportedFormat = ['image/jpeg', 'image/png', 'image/webp'].includes(file.type.toLowerCase())
        // 图片大小限制为10MB
        const isLt10M = file.size / 1024 / 1024 < 10

        if (!isSupportedFormat) {
          this.$message.error('上传头像图片只能是 JPG, JPEG, PNG 或 WEBP 格式!')
        }
        if (!isLt10M) {
          this.$message.error('上传头像图片大小不能超过 10MB!')
        }

        return isSupportedFormat && isLt10M
      },
      /**
     *:on-change="handleAvatarChange"
     文件上传成功时的钩子
     * @param file
     * @param fileList
     */
      handleAvatarChange(file, fileList) {
        if (this.beforeAvatarUpload(file.raw)) {
          this.userForm.avatarFile = file.raw // 保存文件对象
          // 这个方法会返回一个本地的临时路径，用于本地图盘预览 URL.createObjectURL(file.raw)
          this.userForm.avatar = URL.createObjectURL(file.raw)
        } else {
          // 如果不满足条件，则清除已选文件
          this.$refs.userForm.clearFiles()
        }
      },
      /**
       * 重置表单内容
       * @param formName
       */
      resetForm() {
        if (this.$refs.userForm) {
          this.$refs.userForm.resetFields()
          // 清除头像
          this.userForm.avatar = ''
        }
      },
      /**
       * 调教添加用户的表单
       */
      submitForm() {
        this.$refs.userForm.validate(async isOk => {
          if (isOk) {
            // alert('表单各项都校验成功!')
            // 此时创建一个  const formData = new FormData();对象，用于发送表单格式的数据
            const formData = new FormData()
            formData.append('deptId', this.userForm.deptId)
            formData.append('username', this.userForm.username)
            formData.append('nickName', this.userForm.nickName)
            formData.append('email', this.userForm.email)
            formData.append('phoneNumber', this.userForm.phoneNumber)
            formData.append('sex', this.userForm.sex)
            formData.append('avatarFile', this.userForm.avatarFile)
            formData.append('remark', this.userForm.remark)
            await insertUser(formData)

            // 成功之后重置表单 关闭弹窗
            this.closeAddUserDialog()
            // 刷新列表
            this.pageList()

            this.$message.success('上传成功')
          } else {
            // console.log('表单验证失败!')
            return false
          }
        })
      },
      /**
       * 滑动滑块，触发Switch组件的@change事件
       * @param value
       */
      async changeSwitch(userId, status) {
        // console.log(userId, status)
        await updateUserStatus(userId, status)
        this.pageList()
      },
      /**
       * 编辑用户信息
       * @param userId
       */
      async handleEdit(id) {
        const { userId, username, nickName, email, phoneNumber, sex, avatar, remark, deptId } = await findByUserId(id)
        this.editDialogVisible = true
        this.userForm.username = username
        this.userForm.nickName = nickName
        this.userForm.email = email
        this.userForm.phoneNumber = phoneNumber
        this.userForm.sex = sex
        this.userForm.avatar = avatar
        this.userForm.deptId = deptId
        this.userForm.remark = remark
        this.userForm.userId = userId
      },
      /**
       * 删除用户信息
       * @param userId
       */
      handleDelete(userId) {
        this.$confirm('此操作将永久删除该用户, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        })
          .then(async () => {
            await deleteByUserId(userId)
            this.pageList()
            this.$message({
              type: 'success',
              message: '删除成功!'
            })
          })
          .catch(() => {
            this.$message({
              type: 'info',
              message: '已取消删除'
            })
          })
      },
      /**
       * 编辑弹窗的取消功能
       */
      closeEditUserDialog() {
        this.editDialogVisible = false
      },
      /**
       * 确定修改用户信息
       */
      updateSubmitForm() {
        this.$refs.userForm.validate(async isOk => {
          if (isOk) {
            // alert('表单各项都校验成功!')
            // 此时创建一个  const formData = new FormData();对象，用于发送表单格式的数据
            const formData = new FormData()
            formData.append('userId', this.userForm.userId)
            formData.append('deptId', this.userForm.deptId)
            formData.append('username', this.userForm.username)
            formData.append('nickName', this.userForm.nickName)
            formData.append('email', this.userForm.email)
            formData.append('phoneNumber', this.userForm.phoneNumber)
            formData.append('sex', this.userForm.sex)
            // 条件性添加 avatarFile 字段
            if (this.userForm.avatarFile) {
              formData.append('avatarFile', this.userForm.avatarFile)
            }
            formData.append('remark', this.userForm.remark)
            await updateUser(formData)
            // 关闭弹窗
            this.closeEditUserDialog()
            // 刷新列表
            this.pageList()
            this.$message.success('修改成功')
          } else {
            // console.log('表单验证失败!')
            return false
          }
        })
      },
      /**
       * 点击分配角色弹窗
       * @param userId
       */
      handleAssignDialog(user) {
        this.assignShowVisible = true
        this.user = user
      },
      /**
       *配置表格不同行的颜色
       * @param param0
       */
      tableRowClassName({ row, rowIndex }) {
        if (rowIndex === 1) {
          return 'warning-row'
        } else if (rowIndex === 3) {
          return 'success-row'
        }
        return ''
      }
    }
  }
</script>

<style>
  /* 设置全局字体 */
  .tree-container,
  .table-container {
    font-family: 'Arial', sans-serif; /* 或者选择你喜欢的字体 */
    font-size: 14px; /* 统一的字体大小 */
  }

  /* 树形控件的样式 */
  .tree-container {
    border: 1px solid #dcdcdc;
    padding: 10px;
    height: 100%;
  }

  .tree-manager {
    margin-right: 10px; /* 如果需要增加间距 */
  }

  .el-tree-node__content {
    height: auto; /* 自动高度以便适应内容 */
    padding: 5px 0; /* 增加节点之间的间距 */
  }

  /* 表格样式 */
  .table-container {
    margin-top: 10px; /* 如果需要与上方元素保持间距 */
  }

  .el-table th,
  .el-table td {
    font-size: 14px; /* 确保表头和单元格字体大小一致 */
  }

  /* 自定义表格行样式 */
  .el-table .success-row {
    background-color: #f0f9eb;
  }

  .el-table .warning-row {
    background-color: oldlace;
  }

  /* 如果需要进一步定制树形控件的文字颜色或其他样式 */
  .el-tree--highlight-current .el-tree-node.is-current > .el-tree-node__content {
    color: #409eff; /* 当前选中项的颜色 */
  }

  .avatar-uploader .el-upload {
    border: 1px dashed #d9d9d9;
    border-radius: 6px;
    cursor: pointer;
    position: relative;
    overflow: hidden;
  }
  .avatar-uploader .el-upload:hover {
    border-color: #409eff;
  }
  .avatar-uploader-icon {
    font-size: 28px;
    color: #8c939d;
    width: 178px;
    height: 178px;
    line-height: 178px;
    text-align: center;
  }
  .avatar {
    width: 178px;
    height: 178px;
    display: block;
  }
  .preview-image {
    max-width: 100%;
    height: auto;
  }
</style>
